package com.tjetc;

import java.util.*;

public class _2GenericExcercise {
    public static void main(String[] args) {
        /*
            泛型参数：
            E T K V: 仅仅只是一个自定义符号，没有任何的作用 E：Element T：Type K：Key V：Value
            具体的泛型参数名没有任何要求，只是我们习惯上使用上述参数名

            泛型实例化：指的就是将具体的类型添加到<>中

            注意事项：
            1.在给泛型指定具体类型后，可以传⼊该类型或者其⼦类类型，但List<Integer>不是List<Object>的⼦类
            2.泛型会影响方法重载
            3.泛型的类型确定时机是对象实例化的时候
         */

        /*
            泛型在HashSet, HashMap的使⽤情况。
            1. 创建3个学⽣对象
            2. 放⼊到HashSet中学⽣对象。
            3. 放⼊到HashMap中，要求 Key是String name, Value 就是学⽣对象
            4. 使⽤两种⽅式遍历
         */

        Student student = new Student("zhangsan", 1);
        Student student1 = new Student("lisi", 2);
        Student student2 = new Student("wangwu", 3);

        // 省略重写hash和equals
        Set<Student> studentSet = new HashSet<>();
        studentSet.add(student);
        studentSet.add(student1);
        studentSet.add(student2);

        for (Student student3 : studentSet) {
            System.out.println(student3);
        }

        Map<String, Student> studentMap = new HashMap<>(16);
        studentMap.put("zhangsan", student);
        studentMap.put("lisi", student1);
        studentMap.put("wangwu", student2);

        for (Map.Entry<String, Student> entry : studentMap.entrySet()) {
            System.out.println("entry.getKey() = " + entry.getKey());
            System.out.println("entry.getValue() = " + entry.getValue());
        }

        for (String s : studentMap.keySet()) {
            System.out.println(studentMap.get(s));
        }

        // 演示注意事项
        Student student3 = new Student();
        // List<Integer> 和 List<Object> 不是同一类型也没有继承关系
        //  但是在底层JVM在处理的时候他们都是List.class 泛型参数的继承关系不可以
        List<Integer> list = new ArrayList<>();
//        student3.f(list);
        ArrayList<Object> arrayList = new ArrayList<>();
//        student3.f(arrayList);

        // 通过反编译工具可以看出 编译后的结果 List<Object> list1 = new ArrayList<>();
        List list1 = new ArrayList();


    }
}
class Student {
    String name;
    int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Student() {

    }
    // both methods have same erasure
    // 在运行时 List<Object> 和 List<Integer> 都会称为 List<Object>
//    void f(List<Object> list){}
    void f(List<Integer> list){}
}